home *** CD-ROM | disk | FTP | other *** search
- /**
- -- App: QuickDraw GX Scrolling
- --
- -- File: GX Scrolling (main).c
- --
- -- Comments: This code demonstrates scrolling of a window containing GX shapes. I create
- -- a window in the CreateDocumentWindow function. At this point, I attach a
- -- parent viewPort to the window, and a child viewPort to the parent. This
- -- approach enables our application to accommodiate scroll bars and adjust
- -- the child viewPort's gxMapping to reflect scrolling of the window's contents.
- --
- -- You might be wondering, why not just perform the same actions on the parent
- -- viewPort attached to the window? You cannot manipulate the viewPort attached
- -- to the window. All of it's attributes are maintained by the GX system. This
- -- leads to a clipping problems because scroll bars are not really part of the
- -- window's definition.
- --
- -- Therefore, we attach the child viewPort to set it's clip shape within the
- -- scroll bars. Also, we update the mapping of this viewPort when the user scrolls,
- -- thereby guaranteeing that all of the shapes are re-drawn in their correct location.
- -- Another approach, would be to update the location of each shape contained in the
- -- window after scrolling. This would require a lot of work on the application's part.
- -- You would also need to undo this operation at print time because your shapes
- -- would not reside in their correct location relative to a page.
- --
- -- If you are interested in finding the GX additions required to run on a GX
- -- system, search for "GX Additions". If you are only interested in the additions
- -- required to support scrolling in a GX world, search on "GX Scrolling".
- --
- -- The file titled: "GX Scrolling Controls.c" contains of the code required to
- -- maintain, draw, and update the scroll bars.
- --
- --
- -- Version: 1.0 1/93 added general GX support & scrolling
- -- 7/95 Converted to ThinkC 6 and new GX interfaces
- --
- --
- -- Components: QDGX Scrolling main.c
- -- QDGX Scrolling main.h
- -- QDGX Scrolling Controls.c
- -- QDGX Scrolling Controls.h
- -- QDGX Scrolling.π.rsrc
- --
- --
- -- Bugs: If you zoom the window onto a montior which is bigger than the default, you
- -- will receive a GRAPHICS WARNING about how the gxPoint does not intersect the
- -- current gxViewPort. From that gxPoint on, until you resize the window to a smaller
- -- size scrolling will not work correctly. You can create this problem by zooming
- -- from an Apple 16" monitor to a portrait monitor.
- --
- -- I'm currently working on resolving this problem.
- --
- --
- -- Notes: 1) Print this file in landscape for the best results
- -- 2) If you are using THINK C v5.x, I have added THINK markers to navigate the code.
- -- 3) This code was adapted and simplyified from the "DTS AE Skeleton" sample.
- --
- --
- -- Future
- -- Additions: 1) This code should check to make sure it is running under System 7.1 and the
- -- GX system is installed.
- --
- --
- -- Author: Pete "Luke" Alexander
- -- Developer Technical Support
- -- AppleLink: DEVSUPPORT
- --
- --
- -- ©1992 - 1993 Apple Computer, Inc.
- -- All rights reserved.
- --
- **/
-
- #include <AppleEvents.h>
- #include <Desk.h>
- #include <Dialogs.h>
- #include <DiskInit.h>
- #include <Errors.h>
- #include <Fonts.h>
- #include <GestaltEqu.h>
- #include <Menus.h>
- #include <Memory.h>
- #include <OSEvents.h>
- #include <OSUtils.h>
- #include <Quickdraw.h>
- #include <Resources.h>
- #include <SegLoad.h>
- #include <Script.h>
- #include <StandardFile.h>
- #include <ToolUtils.h>
- #include <Windows.h>
-
- #include "QDGX Scrolling main.h"
- #include "QDGX Scrolling Controls.h"
-
- #include <GXEnvironment.h>
- #include <GXGraphics.h>
- #include <GXErrors.h>
- #include "GraphicsLibraries.h"
-
-
- //
- // Prototypes
- //
- void HandleEvent(void);
- void HandleMouseDown(EventRecord *theEvent);
- void HandleKeyPress(EventRecord *theEvent);
- void HandleDiskEvent(EventRecord *theEvent);
- void HandleOSEvent(EventRecord *theEvent);
-
- void DoGrowWindow(WindowPtr theWindow, Point where);
- void DoZoomWindow(WindowPtr theWindow, short thePart);
- void ActivateWindow(WindowPtr theWindow, Boolean activate);
- void FitWindowOnDevice(Rect *windRect, Rect *deviceRect);
- Rect GetDeviceRect(WindowPtr theWindow);
-
- void DoMenu(long menuChoice);
- void DoOpenCommand(void);
- void DoPrintCommand(void);
- void PrintDocument(PicHandle thePicture);
-
- PicHandle ReadDocument(FSSpecPtr mySpec);
- Boolean CreateDocumentWindow(PicHandle thePicture, Str63 name);
- void CloseFrontWindow(void);
- void DrawWindow(WindowPtr theWindow);
- void AdjustMenus(void);
-
- void ToolBoxInit(void);
- void MenuBarInit(void);
- void PrintInit(void);
- Boolean ColorQDAvail(void);
- Boolean FileRoutinesAvail(void);
- void ErrorAlert(short errNumber, Boolean fatal);
- void ShutdownProgram(void);
-
- //
- // The following functions were added to support GX, and add scrolling window support.
- //
- void QuickDrawGXInit(void);
- void GetWindowBoundsShape(WindowPtr myWindow, gxRectangle *boundingBoxPtr);
- gxShape CreateThePageOfGXShapes (gxShape thePage);
- void ResetContentViewPortClip (WindowPtr theWindow);
-
-
- //
- // Global Variables
- //
- Boolean gDone; /* Has the user selected quit? */
- gxGraphicsClient gGraphicsClient;
-
-
- //
- // The variables from this gxPoint on, were added to support QuickDraw™ GX.
- //
-
- //
- // gthePage contain all of the GX shapes which are displayed in the window. gthePage is defined
- // as a gxPictureType in the function CreateShapes. CreateShapes creates all of the shapes
- // contained in gthePage.
- //
- gxShape gthePage;
-
- //
- // This viewPort is the child attached to the window's parent viewPort. Since it is a child viewPort,
- // we (the application) need to maintain the clip shape. We also have the ability to manipulate this
- // ViewPort as we see fit, therefore we adjust the mapping, to reflect scrolling changes by the user.
- //
- gxViewPort gcontentViewPort;
-
-
- //
- // If gDebugging = TRUE, graphics library errors and notices will be posted. This functionality will only work with
- // the "debugging" version of the QuickDraw init. If this version of the init is not installed, nothing bad will happen,
- // but these functions will not work.
- //
- Boolean gDebugging = true;
-
- //
- // Set gGiveMeValidation = TRUE, if you will receive run-time validation.
- //
- Boolean gGiveMeValidation = true;
-
-
- //
- // gGraphicsHeapSize sets the size of the graphics gxHeap created by calling the GXNewGraphicsClient routine
- // in main () within graphics shell.c. You can determine the amount of graphics gxHeap required by using GraphicsBug.
- // With gGraphicsHeapSize set to 25k, I had 2 free blocks left in the graphics gxHeap. Sounds good to me.
- //
- long gGraphicsHeapSize = 25;
-
-
-
- /**----- main --------------------------------------------------------------------------------
- --
- -- Main initializes the application memory, toolbox, menubar, the GX world, and global
- -- variables. We also create a document & window containing our GX picture, which contains
- -- all of our rectangles.
- --
- **/
- main()
- {
- ToolBoxInit();
- MenuBarInit();
- QuickDrawGXInit(); // This function initializes the GX system
- PrintInit();
-
- gDone = false; /* Initialize global variables */
-
- CreateDocumentWindow(nil, "\p QuickDraw GX Scrolling ");
-
- while (!gDone)
- HandleEvent();
- }
-
-
- /**----- ToolBoxInit -------------------------------------------------------------------------
- --
- -- This function initializes the toolbox.
- --
- **/
- void ToolBoxInit(void)
- {
- EventRecord theEvent;
- short count;
-
- /** Generic gxHeap initialization. **/
- MaxApplZone();
- MoreMasters(); MoreMasters(); MoreMasters();
- MoreMasters(); MoreMasters(); MoreMasters();
-
- InitGraf (&qd.thePort);
- InitFonts ();
- FlushEvents(everyEvent, 0);
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
- /* Multi-finder brings our application to the front after */
- /* we ask for three events. */
- for (count=3; count!=0; count--)
- EventAvail(everyEvent, &theEvent);
- }
-
-
- /**----- MenuBarInit -------------------------------------------------------------------------
- --
- -- This function initializes the menus, and installs DAs in the Apple Menu.
- --
- **/
- void MenuBarInit(void)
- {
- Handle theMenuBar;
- MenuHandle appleMenu;
-
- /* Install menus from resources */
- theMenuBar = GetNewMBar(rMenuBar);
- if (theMenuBar == nil)
- ErrorAlert(kNoMenuBarErr, true);
- SetMenuBar(theMenuBar);
- DisposHandle(theMenuBar);
-
- /* Add desk accessories to Apple Menu */
- appleMenu = GetMHandle(mApple);
- if (appleMenu != nil)
- AddResMenu(appleMenu, kDriverType);
-
- DrawMenuBar();
- }
-
-
-
- /**----- QuickDrawGXInit ---------------------------------------------------------------------
- --
- -- This function makes all of the calls required to gxInitialize the GX system, except
- -- for the printing part. For complete details regarding each call made, please see
- -- the comment blocks. (GX Addition)
- --
- **/
- void QuickDrawGXInit(void)
- {
- //
- // The GXNewGraphicsClient routine defines the graphics gxHeap size. If you do not make this call,
- // the GX graphics engine will create this gxHeap automatically. How? It will create a graphics
- // gxHeap of 600k. This call allows you to explicity define the ammount of memory used by the
- // graphics system to store it's graphics objects gxHeap.
- //
- // If you do not pass a value for gGraphicsHeapSize, you will receive the default graphics gxHeap.
- // The GX system will automatically page objects to disk when memory is low.
- //
- gGraphicsClient = GXNewGraphicsClient(nil, gGraphicsHeapSize * 1024, 0L);
-
-
- //
- // If gDebugging = TRUE, you will receive graphics library errors & notices will be posted. This
- // functionality will only work with the "debugging" version of the Secret Graphics init. If this
- // init is not installed, these functions will not work. The "debugging" version of the Secret
- // Graphics init is approximately 810K.
- //
- if (gDebugging) {
- SetGraphicsLibraryErrors ();
- SetGraphicsLibraryNotices();
- }
-
-
- //
- // Set "gGiveMeValidation" to TRUE, if you want run-time validation. As you increase the amount
- // of validation, The drawing speed will SLOW down due to all of the internal checking.
- //
- // gxPublicValidation will check parameters to public routines. For additional details regarding
- // the various levels of validation, please see the documentation.
- //
- if (gGiveMeValidation) GXSetValidation(gxPublicValidation);
-
-
- //
- // Create the default data structures.
- //
- GXEnterGraphics();
-
-
- //
- // Initialize the common colors library defined in "gxColor library.c" and "graphics library.h".
- // This library is a simple method available for you to gxColor an object quickly by calling the
- // the SetShapeCommonColor(...) function.
- //
- InitCommonColors();
- }
-
-
-
- /**----- PrintInit ---------------------------------------------------------------------------
- --
- -- This function will someday gxInitialize the GX Print Manager, if it is present.
- --
- **/
- void PrintInit(void)
- {
-
- }
-
-
-
- /**----- HandleEvent -------------------------------------------------------------------------
- --
- -- This function contains the main event loop.
- --
- **/
- void HandleEvent(void)
- {
- EventRecord theEvent;
- OSErr myErr;
- WindowPtr theWindow;
-
- WaitNextEvent(everyEvent, &theEvent, 30, nil);
-
- switch (theEvent.what)
- {
- case mouseDown:
- HandleMouseDown(&theEvent);
- break;
-
- case keyDown:
- case autoKey:
- HandleKeyPress(&theEvent);
- break;
-
- case updateEvt:
- theWindow = (WindowPtr)theEvent.message;
- BeginUpdate(theWindow);
- if (!EmptyRgn(theWindow->visRgn))
- {
- SetPort(theWindow);
- UpdtControl(theWindow, theWindow->visRgn);
- DrawGrowIcon(theWindow);
- DrawWindow(theWindow);
- }
- EndUpdate(theWindow);
-
- case diskEvt:
- HandleDiskEvent(&theEvent);
- break;
-
- case activateEvt:
- ActivateWindow((WindowPtr)theEvent.message, theEvent.modifiers & activeFlag);
- break;
-
- case osEvt:
- HandleOSEvent(&theEvent);
- break;
-
- case kHighLevelEvent:
- myErr = AEProcessAppleEvent(&theEvent);
- if (myErr != noErr)
- {
- ErrorAlert(kAppleEventErr, false);
- }
- break;
- }
- }
-
-
- /**----- HandleMouseDown ---------------------------------------------------------------------
- --
- -- This functions is called whenever the mouse button is pressed. It finds the mouse
- -- location when the button was pressed and routes the event appropriately.
- --
- **/
- void HandleMouseDown(EventRecord *theEvent)
- {
- short thePart;
- WindowPtr theWindow;
- Rect theRect;
- short controlPart;
- ControlHandle theControl;
-
- thePart = FindWindow(theEvent->where, &theWindow);
- switch (thePart)
- {
- case inMenuBar:
- AdjustMenus();
- DoMenu(MenuSelect(theEvent->where));
- break;
-
- case inSysWindow:
- SystemClick(theEvent, theWindow);
- break;
-
- case inContent:
- if (theWindow != FrontWindow())
- SelectWindow(theWindow);
- else
- {
- SetPort(theWindow);
- GlobalToLocal(&theEvent->where);
- controlPart = FindControl(theEvent->where, theWindow, &theControl);
- if (controlPart != 0)
- DoControl(theEvent->where, theControl, controlPart);
- }
- break;
-
- case inDrag:
- if (theWindow != FrontWindow())
- SelectWindow(theWindow);
- theRect = (**GetGrayRgn()).rgnBBox;
- DragWindow(theWindow, theEvent->where, &theRect);
- break;
-
- case inGrow:
- DoGrowWindow(theWindow, theEvent->where);
- break;
-
- case inGoAway:
- if (TrackGoAway(theWindow, theEvent->where))
- ShutdownProgram();
- break;
-
- case inZoomIn:
- case inZoomOut:
- if (TrackBox(theWindow, theEvent->where, thePart))
- DoZoomWindow(theWindow, thePart);
- break;
- }
- }
-
-
-
- /**----- ResetContentViewPortClip ------------------------------------------------------------
- --
- -- This function resets the clip gxShape of the "gcontentViewPort", to represent the new
- -- clip gxShape after the user has zoomed or resized the window. (GX Scrolling)
- --
- **/
- void ResetContentViewPortClip (WindowPtr theWindow)
- {
- gxRectangle viewRect;
- gxShape contentViewPortClipShape;
-
- //
- // Return a fixed gxPoint gxRectangle in "viewRect" which represents the portRect of the
- // window. This gxShape will be used as the new clip gxShape for "gcontentViewPort".
- GetWindowBoundsShape(theWindow, &viewRect);
-
- //
- // Adjust our viewRect to accommodate the scroll bars
- //
- viewRect.right -= ff(kScrollBarWidth - 1);
- viewRect.bottom -= ff(kScrollBarWidth - 1);
-
- //
- // Create and set the new clip gxShape.
- //
- contentViewPortClipShape = GXNewRectangle(&viewRect);
- GXSetViewPortClip(gcontentViewPort, contentViewPortClipShape);
-
- GXDisposeShape (contentViewPortClipShape);
- }
-
-
-
- /**----- DoGrowWindow ------------------------------------------------------------------------
- --
- -- This function takes care of growing a window after the mouse has been pressed over
- -- the grow icon. It allows maximum growth of the document size or display size, whichever
- -- is smaller. It allows minimum growth to (kMinWindowWidth,kMinWindowHeight) or the
- -- document size, whichever is larger. Finally, it adjusts and redraws the scroll bars
- -- for the new window size.
- --
- **/
- void DoGrowWindow(WindowPtr theWindow, Point where)
- {
- Rect growRect, windRect;
- Rect thePage;
- short width, height;
- long newSize;
- Point origin;
-
- thePage = ((MyWindowPeek)theWindow)->documentBoundsRect;
-
- width = thePage.right - thePage.left + kScrollBarWidth;
- height = thePage.bottom - thePage.top + kScrollBarWidth;
-
- growRect = (**GetGrayRgn()).rgnBBox;
- if (theWindow->portRect.left + width < growRect.right)
- growRect.right = theWindow->portRect.left + width;
-
- if (theWindow->portRect.top + height < growRect.bottom)
- growRect.bottom = theWindow->portRect.top + height;
-
- // Minimum size is (kMinWindowWidth,kMinWindowHeight)
- growRect.left = kMinWindowWidth;
- growRect.top = kMinWindowHeight;
-
- // Make sure maximum size is at least minimum size
- if (growRect.right < growRect.left) growRect.right = growRect.left;
- if (growRect.bottom < growRect.top) growRect.bottom = growRect.top;
-
- /* Allow user to grow the window, then resize it */
- newSize = GrowWindow(theWindow, where, &growRect);
-
- if (newSize != 0)
- {
- GrafPtr saveport;
-
- InvalidateScrollBars(theWindow);
- SizeWindow(theWindow, LoWord(newSize), HiWord(newSize), true);
- InvalidateScrollBars(theWindow);
- ResizeScrollBars(theWindow);
-
- //
- // The user as grown the window, we need to update the clip gxShape of the contentviewPort
- // we attached to the window earlier in the CreateDocumentWindow function. If we did not
- // update the clip gxShape of the contentviewPort clip, we would draw through the scroll
- // bars on the next update event. (GX Scrolling)
- //
- ResetContentViewPortClip(theWindow);
-
-
- /* reposition document */
- origin = ((MyWindowPeek)theWindow)->origin;
- width = theWindow->portRect.right - theWindow->portRect.left - origin.h - width + 1;
- height = theWindow->portRect.bottom - theWindow->portRect.top - origin.v - height + 1;
- if (width < 0) width = 0;
- if (height < 0) height = 0;
-
- if ( (width > 0) || (height > 0) )
- {
- DoScroll(theWindow, width, height);
- ResizeScrollBars(theWindow);
- }
- }
- }
-
-
- /**----- DoZoomWindow ------------------------------------------------------------------------
- --
- -- This function zooms a window. It follows the new human interface guidelines be
- -- dealing with multiple displays. To do this, every time the window is zoomed to the
- -- standard state, it recalculates the standard state based on the display that contains
- -- the largest area of the window. This routine was adapted from Macintosh Technical
- -- Note #79: "_ZoomWindow".
- --
- **/
- void DoZoomWindow(WindowPtr theWindow, short thePart)
- {
- Rect deviceRect, zoomRect;
- Point offset;
- WStateDataHandle windowState;
-
- SetPort(theWindow);
- EraseRect(&theWindow->portRect);
- if ( (thePart == inZoomOut) && (ColorQDAvail()) )
- {
- /* Get window location in global coordinates */
- SetPt(&offset, 0, 0);
- LocalToGlobal(&offset);
-
- deviceRect = GetDeviceRect(theWindow);
-
- zoomRect = ((MyWindowPeek)theWindow)->documentBoundsRect;
- zoomRect.right += kScrollBarWidth-1;
- zoomRect.bottom += kScrollBarWidth-1;
-
- OffsetRect(&zoomRect, -zoomRect.left, -zoomRect.top); /* Adjust upper left to 0,0 */
-
- /* At least minimum window size */
- if (zoomRect.right < kMinWindowWidth-1) zoomRect.right = kMinWindowWidth-1;
- if (zoomRect.bottom < kMinWindowHeight-1) zoomRect.bottom = kMinWindowHeight-1;
-
- OffsetRect(&zoomRect, offset.h, offset.v); /* Align to window */
-
- FitWindowOnDevice(&zoomRect, &deviceRect);
-
- windowState = (WStateDataHandle)((WindowPeek)theWindow)->dataHandle;
- (**windowState).stdState = zoomRect;
- }
- ZoomWindow(theWindow, thePart, true);
- InvalRect(&theWindow->portRect);
-
- ResizeScrollBars(theWindow);
-
- //
- // The user as grown the window, we need to update the "gcontentviewPort" we attached to
- // the window earlier in the CreateDocumentWindow (..) function. If we did not update, the
- // contentviewPort clip, we would draw through the scroll bars on the next update event.
- // (GX Scrolling)
- //
- ResetContentViewPortClip(theWindow);
- }
-
-
-
- /**----- FitWindowOnDevice -------------------------------------------------------------------
- --
- -- This routine takes two rectangles as parameters. windRect is the location of the
- -- window in global coordinates. deviceRect is the boundary of the device in global
- -- coordinates. This routine fits windRect inside deviceRect. windRect is modified,
- -- and upon completion, is where the window should be positioned.
- --
- -- Here's how the algorithm works:
- -- Attempt to leave the window in the same location. If the window doesn't fit inside
- -- the deviceRect, move it to the upper left corner of deviceRect. If the window still
- -- doesn't fit, resize windRect to fit inside the maxRect.
- --
- -- NOTE: Both rectangles must be in the same coordinate system.
- --
- **/
- void FitWindowOnDevice(Rect *windRect, Rect *deviceRect)
- {
- Rect theUnion;
-
- UnionRect(windRect, deviceRect, &theUnion);
- if (!EqualRect(deviceRect, &theUnion)) /* window contained on screen? */
- { /* no, move to upper left corner of maxRect */
- OffsetRect(windRect, deviceRect->left-windRect->left, deviceRect->top-windRect->top);
- UnionRect(windRect, deviceRect, &theUnion);
- if (!EqualRect(deviceRect, &theUnion)) /* window contained on screen? */
- { /* no, resize window to fit */
- if (windRect->right > deviceRect->right)
- windRect->right = deviceRect->right;
- if (windRect->bottom > deviceRect->bottom)
- windRect->bottom = deviceRect->bottom;
- }
- }
- }
-
-
- /**----- GetDeviceRect -----------------------------------------------------------------------
- --
- -- This routine takes a WindowPtr as its parameter. It returns the boundary gxRectangle of
- -- the device that contains the largest area of that window. The rect is returned in
- -- global coordinates.
- --
- **/
- Rect GetDeviceRect(WindowPtr theWindow)
- {
- Rect deviceRect, windRect, theSect;
- GDHandle nthDevice, dominantGDevice;
- long sectArea, greatestArea;
- short bias;
- Point offset;
-
- /* Get portRect in global coordinates */
- windRect = theWindow->portRect;
- SetPt(&offset, 0, 0);
- LocalToGlobal(&offset);
- OffsetRect(&windRect, offset.h, offset.v);
-
- bias = kTitleBarHeight;
- windRect.top -= bias;
-
- /* This loop checks the window against all the gdRects in the gDevice list */
- /* and remembers which gdRect contains the largest portion of the window */
- /* being zoomed. */
- nthDevice = GetDeviceList();
- greatestArea = 0;
- while (nthDevice != nil)
- {
- if (TestDeviceAttribute(nthDevice, screenDevice))
- if (TestDeviceAttribute(nthDevice, screenActive))
- {
- SectRect(&windRect, &(**nthDevice).gdRect, &theSect);
- sectArea = (long)(theSect.right - theSect.left) *
- (theSect.bottom - theSect.top);
- if (sectArea > greatestArea)
- {
- greatestArea = sectArea;
- dominantGDevice = nthDevice;
- }
- }
- nthDevice = GetNextDevice(nthDevice);
- }
-
- /* Create a max zoom gxRectangle, accounting for menu bar height if on main screen */
- if (dominantGDevice == GetMainDevice())
- bias += GetMBarHeight();
- SetRect(&deviceRect, (**dominantGDevice).gdRect.left+3,
- (**dominantGDevice).gdRect.top+bias+3,
- (**dominantGDevice).gdRect.right-3,
- (**dominantGDevice).gdRect.bottom-3);
-
- return(deviceRect);
- }
-
-
- /**----- HandleKeyPress ----------------------------------------------------------------------
- --
- -- This function is called whenever a key is pressed. Since this program has no typed
- -- input, we are only concerned about command key equivalent menu selections.
- --
- **/
- void HandleKeyPress(EventRecord *theEvent)
- {
- char theChar;
-
- theChar = theEvent->message & charCodeMask;
- if ((theEvent->modifiers & cmdKey)!=0)
- {
- AdjustMenus();
- DoMenu(MenuKey(theChar));
- }
- }
-
-
-
- /**----- HandleDiskEvent ---------------------------------------------------------------------
- --
- -- This function checks whether the disk was successfully mounted. If it wasn't, the disk
- -- initialization package is invoked.
- --
- **/
- void HandleDiskEvent(EventRecord *event)
- {
- Point thePoint = {120, 120};
-
- if (HiWord(event->message) != noErr)
- {
- DILoad();
- DIBadMount(thePoint, event->message); /* thePoint is ignored in sys 7+ */
- DIUnload();
- }
- }
-
-
- /**----- HandleOSEvent -----------------------------------------------------------------------
- --
- -- This function is called when OSEvents are received. It handles suspend, resume, and mouse
- -- moved OSEvents.
- --
- **/
- void HandleOSEvent(EventRecord *theEvent)
- {
- WindowPtr theWindow;
-
- switch ((theEvent->message >> 24) & 0x000000ff)
- {
- case suspendResumeMessage:
- if (theEvent->message & 0x00000001) /* resume message */
- {
- SetCursor(&qd.arrow);
- theWindow = FrontWindow();
- if (theWindow != nil)
- ActivateWindow(theWindow, true); /* Activate front window */
- /* Copy contents of clipboard (if changed) to private scrap */
- }
- else /* suspend message */
- {
- theWindow = FrontWindow();
- if (theWindow != nil)
- ActivateWindow(theWindow, false); /* Deactivate front window */
- /* Move private scrap to clipboard */
- }
- break;
-
- case mouseMovedMessage:
- break;
- }
- }
-
-
- /**----- ActivateWindow ----------------------------------------------------------------------
- --
- -- This function activates or deactivates a window, and is called when either an
- -- activate/deactivate event or suspend/resume event is received. The parameters are a
- -- window pointer to the desired window, and a gxBoolean specifying whether to activate
- -- or deactivate the window.
- **/
- void ActivateWindow(WindowPtr theWindow, Boolean activate)
- {
- if (theWindow == nil) /* safety check */
- return;
-
- if (activate) /* activiate window */
- {
- /* Highlight controls */
- DrawGrowIcon(theWindow);
- HiliteControl(((MyWindowPeek)theWindow)->vScrollBar, 0);
- HiliteControl(((MyWindowPeek)theWindow)->hScrollBar, 0);
- /* Restore vertical bar or highlighting */
- /* Enable appropriate menu items */
- }
- else /* deactivate window */
- {
- /* Unhighlight controls */
- DrawGrowIcon(theWindow);
- HiliteControl(((MyWindowPeek)theWindow)->vScrollBar, 255);
- HiliteControl(((MyWindowPeek)theWindow)->hScrollBar, 255);
- /* Remove vertical bar or highlighting */
- /* Disable appropriate menu items */
- }
- }
-
-
-
- /**----- DoMenu ------------------------------------------------------------------------------
- --
- -- This function is called when a menu item has been selected either with the mouse,
- -- or a keyboard equivalent.
- --
- **/
- void DoMenu(long menuChoice)
- {
- short theMenu;
- short theItem;
- MenuHandle appleMenu;
- Str255 accName;
- GrafPtr savePort;
-
- theMenu = HiWord(menuChoice);
- theItem = LoWord(menuChoice);
- switch (theMenu)
- {
- case mApple:
- if (theItem == iAbout)
- Alert(rAboutBox, (ModalFilterProcPtr)nil);
- else
- {
- appleMenu = GetMHandle(mApple);
- if (appleMenu != nil)
- {
- GetItem(appleMenu, theItem, accName); /* Call desk accessory */
- GetPort(&savePort);
- OpenDeskAcc(accName);
- SetPort(savePort);
- }
- }
- break;
-
- case mFile:
- switch (theItem)
- {
- case iOpen:
- DoOpenCommand();
- break;
-
- case iClose:
- CloseFrontWindow();
- break;
-
- case iPageSetup:
- break;
-
- case iPrint:
- DoPrintCommand();
- break;
-
- case iQuit:
- ShutdownProgram();
- break;
- }
- break;
- }
- HiliteMenu(0);
- }
-
-
-
- void DoOpenCommand(void)
- {
- }
-
-
- void DoPrintCommand(void)
- {
- }
-
-
-
- void PrintDocument(PicHandle thePicture)
- {
-
- }
-
-
- PicHandle ReadDocument(FSSpecPtr mySpec)
- {
-
- }
-
-
-
- /**----- GetWindowBoundsShape ----------------------------------------------------------------
- --
- -- This function returns a fixed gxPoint gxRectangle which represents the portRect of the
- -- window. The gxShape returned is used as the new clip gxShape for the gcontentViewPort.
- -- (GX Scrolling)
- **/
- void GetWindowBoundsShape(WindowPtr myWindow, gxRectangle *boundingBoxPtr)
- {
- GrafPtr oldPort;
- Rect qdBounds;
- gxRectangle gxBounds;
- gxValidationLevel currentValidation;
-
- GetPort(&oldPort);
- SetPort(myWindow);
-
- qdBounds = myWindow->portRect; // this is in globals coordinates
-
- //
- // Unfortunately, GXConvertQDPoint(..) will not survive validation with the QD GX ß2
- // seed. Therefore, we get the validation level set up by the application, and turn the
- // validation off. We will reset the validation to it's original setting below.
- //
- // This problem has already been fixed in the QD GX ß3 build, therefore this work around
- // will be removed at ß3. Details about the parameters for the GXConvertQDPoint (..) call
- // can be found in the QD GX ß2 Graphics Notes within the "• Open Me First •" folder.
- //
- currentValidation = GXGetValidation();
- if (currentValidation) GXSetValidation(gxNoValidation);
-
- //
- // Convert the global Quickdraw coordinates to local fixed coordinates.
- //
- GXConvertQDPoint((Point *) &qdBounds.top, 0, (gxPoint *) &gxBounds.left);
- GXConvertQDPoint((Point *) &qdBounds.bottom, 0, (gxPoint *) &gxBounds.right);
-
- //
- // Reset the validation to the original setting.
- //
- if (currentValidation) GXSetValidation(currentValidation);
-
- *boundingBoxPtr = gxBounds;
-
- SetPort(oldPort);
- }
-
-
-
- /**----- CreateThePageOfGXShapes -------------------------------------------------------------
- --
- -- This function creates a GX picture containing the shapes which will be displayed
- -- within our window. In this case, all of the shapes will be rectangles
- -- (GX Addition)
- **/
- gxShape CreateThePageOfGXShapes (gxShape thePage)
- {
- gxShape tempRectangleShape;
- gxRectangle rectangleGeometry = {0, 0, ff(100), ff(100)};
- short loop;
-
- //
- // If the picture passed in has not been created, create an empty GX picture. We set
- // the "gxUniqueItemsShape" attribute because we are adding the same gxRectangle multiple
- // times. This guarantees that each rectagnle will have a "unique" reference within
- // the picture. Otherwise, you would only see the last gxRectangle added to the picture.
- //
- if (thePage == nil)
- {
- thePage = GXNewShape(gxPictureType);
- GXSetShapeAttributes(thePage, gxUniqueItemsShape);
- }
-
- //
- // Create a gxRectangle: rotated 45 degrees, with a close frame fill, and a pen width of 4.
- //
- tempRectangleShape = GXNewRectangle(&rectangleGeometry);
- GXRotateShape(tempRectangleShape, ff(45), ff(50), ff(50));
- GXSetShapeFill(tempRectangleShape, gxClosedFrameFill);
- GXSetShapePen(tempRectangleShape, ff(4));
- GXMoveShape(tempRectangleShape, ff(35), ff(35));
-
- //
- // Set the gxColor of the gxRectangle by calling SetShapeCommonColor (..), and add the
- // gxRectangle to our picture.
- //
- for (loop =1; loop <= 11; loop++)
- {
- SetShapeCommonColor (tempRectangleShape, loop + 5);
- AddToShape(thePage, tempRectangleShape);
- GXMoveShape(tempRectangleShape, ff(60), ff(105));
- }
-
- GXDisposeShape (tempRectangleShape);
-
- return (thePage);
- }
-
-
- /**----- CreateDocumentWindow ----------------------------------------------------------------
- --
- -- This function creates a new document window. We attached a parent gxViewPort to the
- -- window and a child gxViewPort to it. Having the application maintain the child gxViewPort's
- -- clip gxShape and gxMapping will allow use to draw within the scroll bars & update it's
- -- gxMapping to reflect scrolling of the shapes.
- --
- -- The parameters: we ignore the PicHandle at this gxPoint and the str63 containing the
- -- name for the title bar of the window is used.
- --
- -- A gxBoolean is returned indicating success. Failure may result from an running out of
- -- memory in the gxHeap.
- --
- **/
- Boolean CreateDocumentWindow(PicHandle thePicture, Str63 name)
- {
- WindowPtr theWindow;
- ControlHandle hControl, vControl;
- Rect controlRect, deviceRect, windRect, docRect = {0, 0, 1000, 1000};
- Point origin;
-
- /* Allocate space for window */
- theWindow = (WindowPtr)NewPtr(sizeof(MyWindowRecord));
- if (theWindow == nil)
- {
- ErrorAlert(kOutOfMemoryErr, false);
- return(false);
- }
- GetNewWindow(rDocumentWindow, theWindow, (WindowPtr)-1);
-
- ((MyWindowPeek)theWindow)->documentBoundsRect = docRect;
- SetPt(&((MyWindowPeek)theWindow)->origin, 0, 0);
- SetWTitle(theWindow, name);
-
- windRect = ((MyWindowPeek)theWindow)->documentBoundsRect;
-
- windRect.right += kScrollBarWidth-1;
- windRect.bottom += kScrollBarWidth-1;
- OffsetRect(&windRect, -windRect.left, -windRect.top); /* Adjust upper left to 0,0 */
- if (windRect.right < kMinWindowWidth-1) windRect.right = kMinWindowWidth-1;
- if (windRect.bottom < kMinWindowHeight-1) windRect.bottom = kMinWindowHeight-1;
-
- /* Allocate space for HORIZONTAL scroll bar */
- SetRect(&controlRect, 0, 0, 100, 10);
- hControl = NewControl(theWindow, &controlRect, "\p", false, 0, 0, 0, scrollBarProc, 0);
- ((MyWindowPeek)theWindow)->hScrollBar = hControl;
- if (hControl == nil)
- {
- CloseWindow(theWindow);
- DisposePtr((Ptr)theWindow);
- ErrorAlert(kOutOfMemoryErr, false);
- return(false);
- }
-
- /* Allocate space for VERTICAL scroll bar */
- SetRect(&controlRect, 0, 0, 10, 100);
- vControl = NewControl(theWindow, &controlRect, "\p", false, 0, 0, 0, scrollBarProc, 0);
- ((MyWindowPeek)theWindow)->vScrollBar = vControl;
- if (vControl == nil)
- {
- DisposeControl(hControl);
- CloseWindow(theWindow);
- DisposePtr((Ptr)theWindow);
- ErrorAlert(kOutOfMemoryErr, false);
- return(false);
- }
-
- /* POSITION the new window */
- if (FrontWindow() == nil) /* no windows open, use default position */
- { /* Align to upper left of main device */
- OffsetRect(&windRect, 2, 2 + kTitleBarHeight+GetMBarHeight());
- deviceRect = qd.screenBits.bounds;
- deviceRect.left += 3;
- deviceRect.top += 3+GetMBarHeight()+kTitleBarHeight;
- deviceRect.right -= 3;
- deviceRect.bottom -= 3;
- }
- else /* Position down and right from frontmost window */
- {
- SetPort(FrontWindow());
- SetPt(&origin, 0, 0);
- LocalToGlobal(&origin);
- origin.h += kNewWindowOffset;
- origin.v += kNewWindowOffset;
- OffsetRect(&windRect, origin.h, origin.v);
- deviceRect = GetDeviceRect(FrontWindow());
- }
-
- /* Adjust size and position for display */
- /* If not enough room for entire window: */
- /* 1. Position in upper left */
- /* 2. Resize to fit on screen */
- FitWindowOnDevice(&windRect, &deviceRect);
- MoveWindow(theWindow, windRect.left, windRect.top, true);
- SizeWindow(theWindow, windRect.right-windRect.left,
- windRect.bottom-windRect.top, false);
-
- ResizeScrollBars(theWindow); /* Initialize Scroll Bars */
-
- ShowControl(hControl);
- ShowControl(vControl);
- ShowWindow(theWindow);
-
- //
- // We need to attach a couple of viewPorts to the window to allow our
- // GX shapes to be clipped and scrolled correctly. (GX Scrolling)
- //
- {
- gxRectangle viewRect;
- gxViewPort windowParentViewPort;
- gxShape contentViewPortShape;
-
- //
- // Get a rectangle shape which represents the portRect of the
- // window. This shape will be used as the clip shape for the
- // "gcontentViewPort". This gxViewPort will have all of our
- // GX objects drawn to.
- //
- GetWindowBoundsShape(theWindow, &viewRect);
-
- //
- // Adjust our viewRect to accommodate the scroll bars
- //
- viewRect.right -= ff(kScrollBarWidth - 1);
- viewRect.bottom -= ff(kScrollBarWidth - 1);
-
- //
- // Add a viewPort to the window. This will enable the
- // user to move the window around and have our GX objects
- // drawn into the window.
- //
- windowParentViewPort = GXNewWindowViewPort(theWindow);
-
- //
- // Create a second viewPort and attached it to the "parent"
- // viewPort of our window. You cannot manipulate the parent
- // viewPort attached to a window, but you can manipulate it's
- // child. We will manipulate the clip and gxMapping of this viewPort
- // when the user resizes the window or scrolls it's contents. Also, we
- // need this child viewPort because we want to set the clip shape of the
- // window to reside within the scroll bars, not on top of them, which would
- // be the case if we only used the parent viewPort.
- //
- gcontentViewPort = GXNewViewPort(GXGetViewPortViewGroup(windowParentViewPort));
-
- //
- // Set up the shape, clip and, mapping of our "gcontentViewPort". We will
- // then attached it to the "parent" viewPort of the window.
- //
- contentViewPortShape = GXNewRectangle(&viewRect);
- GXSetViewPortClip(gcontentViewPort, contentViewPortShape);
- GXSetViewPortMapping(gcontentViewPort, nil);
- GXSetViewPortParent(gcontentViewPort, windowParentViewPort);
- GXDisposeShape (contentViewPortShape);
-
- //
- // By calling SetDefaultViewPort (..), all shapes we create will
- // be automatically drawn to "gcontentViewPort".
- //
- GXIgnoreGraphicsNotice(transform_already_set);
- SetDefaultViewPort(gcontentViewPort);
- GXPopGraphicsNotice();
-
- gthePage = CreateThePageOfGXShapes (nil);
- }
-
- return(true);
- }
-
-
- /**----- CloseFrontWindow --------------------------------------------------------------------
- --
- -- This function closes the frontmost window and disposes of the window record allocated
- -- on the gxHeap for it.
- --
- **/
- void CloseFrontWindow(void)
- {
- WindowPtr theWindow;
-
- theWindow = FrontWindow();
- if (theWindow!=nil)
- {
- CloseWindow(theWindow);
- DisposePtr((Ptr)theWindow);
- }
- }
-
-
-
- /**----- DrawWindow --------------------------------------------------------------------------
- --
- -- This function draws the contents of the window without overwriting the scroll bars.
- --
- **/
- void DrawWindow(WindowPtr theWindow)
- {
- PicHandle thePicture;
- Rect tempRect;
- Point origin;
- RgnHandle saveClip;
-
- SetPort(theWindow);
-
- saveClip = NewRgn(); /* Remove scroll bar areas from clipRgn */
- GetClip(saveClip);
- tempRect = theWindow->portRect;
- tempRect.right -= (kScrollBarWidth-1);
- tempRect.bottom -= (kScrollBarWidth-1);
- ClipRect(&tempRect);
-
- SetClip(saveClip); /* Restore clipRgn */
- DisposeRgn(saveClip);
-
- //
- // Draw the shapes contained within our GX picture gxShape - gthePage (GX Addition)
- //
- GXDrawShape (gthePage);
- }
-
-
- /**----- AdjustMenus -------------------------------------------------------------------------
- --
- -- This function is called immediately before each time the user makes a menu selection.
- -- It enables/disables the appropriate menu items based on the current state of the
- -- program. In version 1.0, we do not update the menus. We only support "quit".
- **/
- void AdjustMenus(void)
- {
- }
-
-
-
- /**----- FileRoutinesAvail -------------------------------------------------------------------
- --
- -- This function is used before calling FSSpec routines to see if they are available.
- -- Note that MPW 3.2 and THINK C 5.0 both include glue that let you use Gestalt even if
- -- it is not in ROM or in the System File. If you are not using one of these environments,
- -- and you don't have Gestalt glue, you will need to use the TrapAvailable check (as shown
- -- in Inside Macintosh VI 3-8) to determine whether the Gestalt call exists before calling
- -- it.
- **/
- Boolean FileRoutinesAvail(void)
- {
- long response;
-
- if (Gestalt(gestaltFSAttr, &response) == noErr)
- if ((response >> gestaltHasFSSpecCalls) & 0x00000001)
- if (Gestalt(gestaltStandardFileAttr, &response) == noErr)
- if ((response >> gestaltStandardFile58) & 0x00000001)
- return(true);
- return(false);
- }
-
-
-
- /**----- ColorQDAvail ------------------------------------------------------------------------
- --
- -- This function is used before calling Color QuickDraw routines to see if they are
- -- available. Note that MPW 3.2 and THINK C 5.0 both include glue that let you use
- -- Gestalt even if it is not in ROM or in the System File. If you are not using one of
- -- these environments, and you don't have Gestalt glue, you will need to use the
- -- TrapAvailable check (as shown in Inside Macintosh VI 3-8) to determine whether the
- -- Gestalt call exists before calling it.
- --
- **/
- Boolean ColorQDAvail(void)
- {
- long response;
-
- if (Gestalt(gestaltQuickdrawVersion, &response) == noErr)
- if ((response & 0x0000ffff) >= gestalt8BitQD)
- return(true);
- return(false);
- }
-
-
-
- /**----- ErrorAlert --------------------------------------------------------------------------
- --
- -- This function displays an error message in an alert. The error number corresponds
- -- to an error message in a 'str#' resource. This message is displayed in a dialog box.
- -- The Boolean parameter is true for a fatal error, and will cause the program to
- -- immediately terminate instead of returning.
- --
- **/
- void ErrorAlert(short errNumber, Boolean fatal)
- {
- Str255 errorString;
-
- GetIndString(errorString, rErrorStrings, errNumber);
-
- ParamText(errorString, "\p", "\p", "\p");
- if (fatal)
- {
- StopAlert(rFatalErrorAlert, nil);
- ExitToShell();
- }
- else
- NoteAlert(rNonFatalErrorAlert, nil);
- }
-
-
-
- /**----- ShutdownProgram ---------------------------------------------------------------------
- --
- -- This function is called before normal termination of the program. It sets the event
- -- loop done variable to true, so the program will exit at the end of the event loop. We
- -- call CloseFrontWindow() to dispose of our window and data structure containing our
- -- document information.
- --
- -- If this program had editing capabilities, this is where the user would be asked if
- -- he wanted to save any changed documents before quitting.
- --
- **/
- void ShutdownProgram(void)
- {
- WindowPtr theWindow;
-
- gDone = true;
-
- //
- // If we created a GX picture which contains our window full of information, we wnat to
- // dispose of it, by callling GXDisposeShape. We call DisposeCommonColor () because we
- // initialized the common colors library earlier in the QuickDrawGXInit function.
- // (GX Addition)
- if (gthePage != nil) GXDisposeShape(gthePage);
-
- DisposeCommonColors();
-
- //
- // This function call will dispose of the data contained in the window.
- //
- CloseFrontWindow();
-
- //
- // Deallocate all of the default data and memory structures for the GX
- // graphics and layout system. (GX Addition)
- //
- GXExitGraphics();
- GXDisposeGraphicsClient(gGraphicsClient);
- }
-